#ifndef PHYSICS_FACTORY_H
#define PHYSICS_FACTORY_H

#include "btBulletDynamicsCommon.h"
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
#include "BulletDynamics/Character/btKinematicCharacterController.h"
#include <vector>

using namespace std;

class PhysicsFactory
{
public:
	~PhysicsFactory();

	static PhysicsFactory * GetInstance();

	btRigidBody * CreateSquareRigidBody(float mass, float posX, float posY, float posZ, float rotX, float rotY, float rotZ, float rotW, float halfWidth, float halfHeight, float halfDepth);
	btRigidBody * CreateRigidBody(float mass, float posX, float posY, float posZ, float rotX, float rotY, float rotZ, float rotW, btCollisionShape *a_shape);
	btRigidBody * CreateRigidBody(float mass, btTransform *trans, btCollisionShape *a_shape);
	btCollisionShape * CreateSquareShape(float halfWidth, float halfHeight, float halfDepth);
	btCollisionShape * CreateSquareShape(btVector3 *vec);
	btCollisionShape * CreateCapsuleShape(float radius, float height);
	btCollisionShape * CreatePlaneShape(float x, float y, float z, float w);

	void DestroyRigidBody(btRigidBody *a_body);
	void DestroyConstraint(btTypedConstraint *a_constraint);
		

	btDynamicsWorld * CreateWorld(float aabbMinX, float aabbMinY, float aabbMinZ, float aabbMaxX, float aabbMaxY, float aabbMaxZ, float gravityX, float gravityY, float gravityZ);

	btDynamicsWorld * GetWorld();

	void AddRigidBodyToWorld(btRigidBody* a_body);
	void RemoveRigidBodyFromWorld(btRigidBody* a_body);
	void AddConstraintToWorld(btTypedConstraint *a_constraint);
	void AddConstraintToWorld(btTypedConstraint *a_constraint, bool disableCollisionBetweenConnectedBodies);
	void RemoveConstraintFromWorld(btTypedConstraint *a_constraint);

	
	btTypedConstraint * CreateHingeConstraint(btRigidBody *a_body,btRigidBody *b_body, btVector3 *pivotPosInA, btVector3 *pivotPosInB, btVector3 *axisInA, btVector3 *axisInB, float minLimit, float maxLimit);

	btTypedConstraint *  CreateHingeConstraint(btRigidBody *a_body,btRigidBody *b_body, btTransform *localA, btTransform *localB, float limit);

	btTypedConstraint *  CreateHingeConstraint(btRigidBody *a_body,btRigidBody *b_body, btTransform *localA, btTransform *localB, float minLimit, float maxLimit);

	//btTypedConstraint *  CreateTwistConstraint(btRigidBody *a_body,btRigidBody *b_body, btTransform *localA, btTransform *localB, float minLimit, float maxLimit);
	btTypedConstraint *  CreateTwistConstraint(btRigidBody *a_body,btRigidBody *b_body, btTransform *localA, btTransform *localB, float twistSpan, float swingSpan1, float swingSpan2);

	btTypedConstraint *  CreatePoint2PointConstraint(btRigidBody *a_body,btRigidBody *b_body, btTransform *localA, btTransform *localB);

	btTypedConstraint *  CreatePoint2PointConstraint(btRigidBody *a_body,btRigidBody *b_body, btVector3 *pivotPosInA, btVector3 *pivotPosInB);


private:
	PhysicsFactory();

	static PhysicsFactory * m_instance;

	std::vector<btCollisionShape*> *m_collisionShapes;
	std::vector<btRigidBody*> *m_rigidBodies;

	std::vector<btTypedConstraint *> *m_constraints;

	btDiscreteDynamicsWorld *m_world;

	btDefaultCollisionConfiguration *m_collisionConfiguration;
	btConstraintSolver *m_constraintSolver;
	btBroadphaseInterface *m_broadPhaseInterface;
	btCollisionDispatcher *m_collisionDispatcher;

	
};
#endif